package com.hcss.common.util;

import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;

/**
 * @function : 文件工具类
 */
public class FileUtil {
    private static final Logger logger = LoggerFactory.getLogger(FileUtil.class);
	public static final int streamReadCount = 1 * 1024;
	public static final String dirSperator = "/";
	public static final String fileSperator = ".";
	public static final String createPrefix = "_";
	public static final String errorMsg = "上传失败";
	
	/**
	 * 判断当前文件是否存在
	 * @param filePath
	 * @return
	 */
	public static Boolean isExit(String filePath){
		File file = new File(filePath);
		
		return file.exists();
	}
	
	/**
	 * 创建一个文件名称
	 * @param hashCode
	 * @param type
	 * @return
	 */
	public static String createFileName(String type, int hashCode){
		type = EmptyUtil.isHaveEmpty(type) ? "" : type;
		Long timestamp = System.nanoTime();
		
		return type + createPrefix +timestamp+ createPrefix + hashCode + fileSperator + type;
	}
	
	/**
	 * 根据前缀和类型形成文件名称
	 * @param type
	 * @param prefix
	 * @return
	 */
	public static String createFileName(String type, String prefix){
		type = EmptyUtil.isHaveEmpty(type) ? "" : type;
		Long timestamp = System.nanoTime();
		
		return prefix + createPrefix +timestamp+ fileSperator + type;
	}
	
	/**
	 * 根据文件的路径名或者文件名称获取文件的后缀名（既是类型名称）
	 * aa.txt - > txt
	 * @param pathOrName
	 * @return
	 */
	public static String getFileType(String pathOrName){
		if(EmptyUtil.isHaveEmpty(pathOrName) || EmptyUtil.isHaveEmpty(pathOrName.trim())){
			return null;
		}
		
		String[] splite = pathOrName.split("\\\\");
		splite = splite[splite.length - 1].split("/");
		splite = splite[splite.length - 1].split("\\.");
		
		return splite[splite.length - 1];
	}
	
	/**
	 * 获取文件的名称没有后缀名 aa.txt - > aa
	 * @param pathOrName
	 * @return
	 */
	public static String getFileName(String pathOrName){
		if(EmptyUtil.isHaveEmpty(pathOrName) || EmptyUtil.isHaveEmpty(pathOrName.trim())){
			return null;
		}
		String fileName = "";
		
		String[] splite = pathOrName.split("\\\\");
		splite = splite[splite.length - 1].split("/");
		splite = splite[splite.length - 1].split("\\.");
		
		for(int i = 0; i < splite.length - 1; i++){
			fileName += (splite[i] + ".");
		}
		return EmptyUtil.isHaveEmpty(fileName) ? "" : fileName.substring(0, fileName.length() - 1);
	}

	/**
	 * 将输入流保存到指定的文件目录下
	 * 由于每次读的粒度比较大，所以导致存储的文件的大小会大于原来的输入流
	 * @param is
	 * @param filePath
	 * @throws Exception
	 */
	public static void save(InputStream is, String filePath) throws Exception{
        save(is, filePath, streamReadCount);
	}

    /**
     * 将输入流保存到指定的文件目录下
     * 由于每次读的粒度比较大，所以导致存储的文件的大小会大于原来的输入流
     * @param is
     * @param filePath
     * @param count 指定每次读取大小
     * @throws Exception
     */
	public static void save(InputStream is, String filePath, int count) throws Exception{
		if(EmptyUtil.isHaveEmpty(is, filePath)){
			return;
		}
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(new File(filePath));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			throw e;
		}
		byte[] b = new byte[count];
		try {
			while (is.read(b) != -1) {
				fos.write(b);
			}
		} catch (IOException e) {
			e.printStackTrace();
			throw e;
		} finally {
			StreamUtil.close(is);
			StreamUtil.close(fos);
		}
	}

	/**
	 * 其他类型转换成文件
	 * 注意，可以没有这个文件，但是一定要有文件之前的目录
	 * @param file
	 * @param filePath
	 * @return
	 */
	public static Boolean save(MultipartFile file, String filePath) {
		if (EmptyUtil.isHaveEmpty(file, filePath)) {
			return null;
		}
		File newFile = new File(filePath);
		if(!newFile.exists()){
			try {
				createFile(filePath);
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			}
		}
		try {
			file.transferTo(newFile);//TODO 创建出错，无法转换
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	
	/**
	 * 将文件保存在指定的文件中
	 * @param filePath
	 * @param content
	 * @throws IOException
	 */
	public static void save(String filePath, String content) throws IOException{
		FileOutputStream fos = null;
		try {
			createFile(filePath);
			fos = new FileOutputStream(new File(filePath));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			throw e;
		}
		try {
			fos.write(content.getBytes());
		} catch (IOException e) {
			e.printStackTrace();
			throw e;
		} finally {
			StreamUtil.close(fos);
		}
	}
	
	/**
	 * 递归创建对应的目录和一个空文件
	 * @param filePath
	 * @throws IOException
	 */
	public static void createFile(String filePath) throws IOException{
		File file = null;
		filePath = filePath.replace("\\", "/");//TODO 这里对linux处理是有问题的 filePath = filePath.replace("/", "\\");
		for(int i = 0; i < filePath.length(); ){
			i = filePath.indexOf("/", i + 1);
			if(i != -1){
				file = new File(filePath.substring(0, i));
				if(!file.exists()){
					file.mkdir();
				}
			}else{
				file = new File(filePath);
				if(!file.exists()){
					file.createNewFile();
				}
				break;
			}
		}
	}
	
	/**
	 * 创建文件
	 * @param filePath 所要创建的文件的地址
	 * @return 是否创建文件成功
	 */
	public static boolean creatFile(String filePath) {
		
		File file = new File(filePath);
		
		if(file.exists()){
			System.out.println("创建文件失败，文件已存在！");
			return false;
		}
		if(filePath.endsWith(File.separator)){
			System.out.println("创建文件失败，目标文件不能为目录");
			return false;
		}
		
		if(!file.getParentFile().exists()) {  
			//如果目标文件所在的目录不存在，则创建父目录  
			 if(!file.getParentFile().mkdirs()) {  
                System.out.println("创建目标文件所在目录失败！");  
                return false;  
            }  
		}
		try {
			return file.createNewFile( );
        } catch (IOException e) {  
        	System.out.println("创建文件失败...");
            return false;  
        }  
	}
	
	/**
	 * 创建文件夹
	 * @param dirPath 所要创建文件夹的地址
	 * @return 是否创建成功
	 */
	public static boolean createDir(String dirPath) {
		File dir = new File(dirPath);  
        if (dir.exists()) {  
            System.out.println("创建目录" + dirPath + "失败，目标目录已经存在");  
            return false;  
        }  
        if (!dirPath.endsWith(File.separator)) {  
        	dirPath = dirPath + File.separator;  
        }  
        //创建目录  
        if (dir.mkdirs()) {  
            System.out.println("创建目录" + dirPath + "成功！");  
            return true;  
        } else {  
            System.out.println("创建目录" + dirPath + "失败！");  
            return false;  
        }  
	}

    /**
     * 删除文件
     * @param filePath
     */
	public static void delete(String filePath) {
	    if (!EmptyUtil.isHaveEmpty(filePath)) {
            File file = new File(filePath);
            // 判断目录或文件是否存在
            if (file.exists() && file.isFile()) {
                file.delete();
            }
        }
    }

    /**
     * 获取文件保存到本地的名称：时间戳+文件后缀
     * @param name
     * @return
     */
    public static String getFilePathName(String name) {
        return System.nanoTime() + fileSperator + getFileType(name);
    }

    /**
     * 根据文件名和路径实现页面下载功能
     * @param response
     * @param fileName
     * @param path
     */
    public static void download(HttpServletResponse response, String fileName, String path) {
        response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");
        InputStream inputStream = null;
        OutputStream os = null;
        try {
            response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));

            inputStream = new FileInputStream(new File(path));
            os = response.getOutputStream();
            byte[] b = new byte[2048];
            int length;
            while ((length = inputStream.read(b)) > 0) {
                os.write(b, 0, length);
            }
            os.close();
            inputStream.close();
        } catch (IOException e) {
            logger.error("下载文件出错，" + e.getMessage() + ", path=" + path, e);
        } finally {
            StreamUtil.close(os);
            StreamUtil.close(inputStream);
        }
    }

    /**
     * 根据Workbook 下载excel文件
     * @param response
     * @param fileName
     * @param wb
     */
    public static void downloadExcelByWorkbook(HttpServletResponse response, String fileName, Workbook wb){
    	response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ByteArrayInputStream inputStream = null;
        OutputStream os = null;
        try {
        	wb.write(bos);
        	byte[] content = bos.toByteArray();
        	inputStream = new ByteArrayInputStream(content);
            response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));
            
            os = response.getOutputStream();
            byte[] b = new byte[2048];
            int length;
            while ((length = inputStream.read(b, 0, b.length)) > 0) {
                os.write(b, 0, length);
            }
            os.close();
            inputStream.close();
        } catch (IOException e) {
            logger.error("下载" + fileName + "文件出错，" + e.getMessage(), e);
        } finally {
        	StreamUtil.close(bos);
        	StreamUtil.close(os);
            StreamUtil.close(inputStream);
        }
    }
   
}